package main

/*
gRPC让我们可以像本地调用一样实现远程调用，对于每一次的RPC调用中，都可能会有一些有用的数据，而这些数据就可以通过metadata来传递。
metadata是以key-value的形式存储数据的，其中key是string类型，而value是[]string即一个字符串数组类型。
metadata使得client和server能够为对方提供关于本次调用的一些信息，就像一次http请求的RequestHeader和ResponseHeader一样。
http中header的生命周周期是一次http请求，那么metadata的生命周期就是一次RPC调用。
*/
import (
	"context"
	"fmt"
	"google.golang.org/grpc"
	"google.golang.org/grpc/metadata"
	"learn_grpc/5_grpc_metadata/proto"
	"net"
)

// 业务逻辑，这里就和服务端写在一起，通常是放到handler里面的
type Server struct{}

// 在grpc的方法参数是固定格式第一个context.Context类型，第二个指针类型的请求参数。返回值为第一个指针类型的响应，第二个为error
func (s *Server) SayHello(ctx context.Context, request *proto.HelloRequest) (*proto.HelloReply, error) {
	//通过metadata.FromIncomingContext获取传递过来的ctx中的metadata的数据
	md, ok := metadata.FromIncomingContext(ctx)
	if ok {
		fmt.Println("get metadata error ")
	}
	// 打印传递的值
	for key, value := range md {
		fmt.Println("key: ", key, "value: ", value)
	}
	//单独打印其中某个值
	if nameSlice, ok := md["name"]; ok {
		for index, value := range nameSlice {
			fmt.Println("index: ", index, "value: ", value)
		}
	}

	return &proto.HelloReply{Message: "Hello " + request.Name}, nil
}

func main() {
	//服务端三步走，第一步：实例化server
	Gserver := grpc.NewServer()
	// 第二步：将业务逻辑注册到server，采用的是proto自动生成的封装注册函数
	proto.RegisterGreeterServer(Gserver, &Server{})
	//第三步： 启动server,先定义端口地址等
	listener, err := net.Listen("tcp", ":8080")
	if err != nil {
		panic("listen fail" + err.Error())
	}
	err = Gserver.Serve(listener)
	if err != nil {
		panic("serve fail" + err.Error())
	}
}
